#include "BDB.h"
extern mr_log_p bdb_log;
extern mr_conf_p pconf;

#define NODUP 0
#define DUP   1
#define NOSECOND 0
#define SECOND   1
#define DBMASK_EXTENTION  2 
#define DBMASK_USERS  3
#define DBMASK_DIALPLAN 4

dbs_t dbs;

typedef struct { 
	long unsigned int mask ; /* mask */
	DB **dbpp ; /* pointer to the DB handle in dbs */
	const char *file; /* the file in wich db lives  */
	int dup ; /* ALLOW duplicated entries */
	int (*cmp_func)(DB *db,const DBT * dbt1,const DBT *dbt2, size_t *locp); /*comparison function*/
	int secondary; /* ALLOW isecondaryduplicated entries */
//	int (*secondary_func)(DB *db,const DBT * dbt1,const DBT *dbt2); /*comparison function*/
	int (*secondary_func)(DB *secondary,const DBT *key, const DBT *data, DBT *result);
	DB **sdbpp; /*secondary db pointer */
}database_t;

#include "dbconf.c"


int database_open(int flag){

	int ret; 
	int i ;

	 /** Create an environment object and initialize it for error
         * reporting.
         */
	if ((ret = db_env_create(&(dbs.dbenv), 0)) != 0) {
		mr_logger_write(bdb_log,LL_ERROR," %s\n",
		db_strerror(ret));
		return (1);
	}	
	
        if ((ret = dbs.dbenv->set_cachesize(dbs.dbenv, 0, 64 * 1024, 0)) != 0) {
                mr_logger_write(bdb_log,LL_ERROR,"set_cachesize : %s\n",
                                db_strerror(ret));
                dbs.dbenv->close(dbs.dbenv, 0);
                return (1);
        }
        (void)dbs.dbenv->set_data_dir(dbs.dbenv,dbs.data_dir);
        
	if ((ret =dbs.dbenv->open(dbs.dbenv,dbs.data_dir,
            DB_CREATE | DB_INIT_MPOOL , 0644)) != 0) {
                mr_logger_write(bdb_log,LL_TRACE, "environment open: %s",dbs.data_dir);
                if (ret == ENOENT){
                        mr_logger_write(bdb_log,LL_ERROR,
				" Please check whether home dir \"%s%s\" existed.\n", 
				dbs.data_dir,
                                db_strerror(ret));
                }
                dbs.dbenv->close(dbs.dbenv, 0);
                return (1);
        }

	for (i=0;databases[i].mask;i++){
	DB *dbp;    /* For convenience */	

		if(*databases[i].dbpp) continue;
		/* initialize DB Handler*/
		ret=db_create(&dbp,NULL,0);
		if(ret !=0){
			mr_logger_write(bdb_log,LL_ERROR,"%s\n",db_strerror(ret));
			return (ret);
		}
		/* point to the memory allocated by db_create */
		*databases[i].dbpp=dbp;
		/* setup key duplication if needed */ 
		if(databases[i].dup){

			ret = dbp->set_flags(dbp,DB_DUPSORT);
			if(ret !=0){
				mr_logger_write(bdb_log,LL_ERROR,
					"ERROR :can't set DB_DUPSORT flag %s:%s\n"
					,databases[i].file,db_strerror(ret));
				dbp->close(dbp,0);

			}
		}
		/* Set key Comparison function if needed */
		if(databases[i].cmp_func){
			ret=dbp->set_bt_compare(dbp,databases[i].cmp_func);
			if(ret!=0){
				mr_logger_write(bdb_log,LL_ERROR,
					"ERROR :can't set compare functiong %s:%s\n"
					,databases[i].file,db_strerror(ret));
				dbp->close(dbp,0);
				return (ret);				
			}
		}
        
	//	if(databases[i].dup){
	//	flag = DB_CREATE | DUP ;
	//	}
		/* now Open The Database */
		ret = dbp->open(dbp,   /* pointer to the database*/
				NULL, /* TXN pointer */
				databases[i].file,  /* file name */
				 NULL,       /* Logical db name (unneeded) */
				DB_BTREE,   /* database typr (using btree) */
				flag, /* open flags*/
				0); /* file mode using DEFAULT */
		if(ret!=0){
			mr_logger_write(bdb_log,LL_ERROR,
					"ERROR :can't set compare functiong %s:%s\n"
					,databases[i].file,db_strerror(ret));
			dbp->close(dbp,0);
			return (ret);				
		}
		
	       /* Associate the secondary with the primary. */
		if(databases[i].secondary){
		/*DB *sdbp;     For convenience */	
	/*	ret=dbp->associate(dbp,NULL,databases[i].sdbpp,databases[i].secondary_func,0);
			if(ret!=0){
				mr_logger_write(bdb_log,LL_ERROR,
					"ERROR :can't set secondary functiong %s:%s\n"
					,databases[i].file,db_strerror(ret));
				dbp->close(dbp,0);
				return (ret);				
			}
	*/
		/* point to the memory allocated by db_create */
		//	*databases[i].sdbpp=sdbp;
		}
	}
ret=	dbs.name2ext->associate(dbs.extention, NULL, dbs.name2ext, db_name_extentionid, 0);
			if(ret!=0){
				mr_logger_write(bdb_log,LL_ERROR,
					"ERROR :can't set secondary functiong %s\n"
					,db_strerror(ret));
				dbs.name2ext->close(dbs.name2ext,0);
				return (ret);				
			}

	    if (ret != 0)
		return (ret);
	return 0;
}
int database_close( ){
	

	int i, ret, ret1=0;

	if ((ret =dbs.dbenv->close(dbs.dbenv, 0)) != 0) {
		fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
		return (1);
	}
	for (i=0; databases[i].mask; i++)/* go to the end */;
	  for (i--; i>=0; i--){
	    if (*databases[i].dbpp == NULL) continue;
	    ret = (*databases[i].dbpp)->close(*databases[i].dbpp, 0);
		
	    if (ret != 0)
	      fprintf(stderr, "Error: database close failed: %s\n",
		db_strerror(ret));
	    ret1 += (ret!=0);
	  }
	  	
	  return ret1;
        /* Close the environment handle. */


    
	/*free(my_switch->users_db_name);
	free(my_switch->directory_db_name);
	free(my_switch->dialplan_db_name);*/
	printf("databases closed.\n");
	return (0);
}

/* create DBT object of various type */

DBT mk_empty_dbt(){
  DBT ret;
  memset(&ret, 0, sizeof(DBT));
  return ret;
}

DBT mk_uint_dbt(unsigned int * i){
  DBT ret;
  memset(&ret, 0, sizeof(DBT));
  ret.data = i;
  ret.size = sizeof(int);
  return ret;
}

DBT mk_string_dbt(const char * str){
  DBT ret;
  memset(&ret, 0, sizeof(DBT));
  ret.data = (char *) str;
  ret.size = strlen(str)+1;
  return ret;
}

int
compare_uint(DB *dbp, const DBT *a, const DBT *b, size_t *lockp){
    unsigned int ai, bi;
    *lockp = 0;
    memcpy(&ai, a->data, sizeof(int));
    memcpy(&bi, b->data, sizeof(int));
    return (ai - bi);
}

int
compare_string(DB *dbp, const DBT *a, const DBT *b, size_t *lockp){
//	*lockp = 0;
    return strcmp(a->data, b->data);
}
/*********************************************************************/

void
remove_html(char * str, int rem_nl){
  int i;
  for (i=0; i<strlen(str); i++){
    if (str[i]=='<') str[i]='[';
    if (str[i]=='>') str[i]=']';
    if (rem_nl && str[i]=='\n') str[i]=' ';
  }
}

	
	
